<?php

namespace App\Models;

use Barryvdh\LaravelIdeHelper\Eloquent;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

/**
 * App\Models\Product
 *
 * @property int $id
 * @property string $title
 * @property int|null $sort 排序，数字越大越靠前。
 * @property int|null $store_id
 * @property string $cover 封面
 * @property array|null $images 商品的轮播图
 * @property int|null $p_rate 上级返点百分比
 * @property int|null $p_p_rate 上上级返点百分比
 * @property string $detail_image 详情长图
 * @property string|null $miaosha_start 秒杀开始时间
 * @property string|null $miaosha_end 秒杀结束时间
 * @property int|null $is_banner  置顶顺序。0为不置顶。
 * @property string $hexiao_type 核销方式：1：到店核销；2：物流快递。
 * @property string|null $hexiao_mobile 核销手机号
 * @property string|null $hexiao_end 到店核销截止日期
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property Carbon|null $deleted_at
 * @property-read Cate $cate
 * @property-read Collection|ProductSku[] $skus
 * @property-read int|null $skus_count
 * @property-read Store|null $store
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newQuery()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Product onlyTrashed()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product query()
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereCover($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereDeletedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereDetailImage($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereHexiaoEnd($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereHexiaoMobile($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereHexiaoType($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereImages($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereMiaoshaEnd($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereMiaoshaStart($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereMiaoshaTop($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product wherePPRate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product wherePRate($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereSort($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereStoreId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereTitle($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUpdatedAt($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Product withTrashed()
 * @method static \Illuminate\Database\Query\Builder|\App\Models\Product withoutTrashed()
 * @mixin Eloquent
 */
class Product extends Model
{
    use SoftDeletes;

    const PRODUCT_SKUS = 'product_skus';

    protected $fillable = [
        'cate_id','title','keyword','description','cover','images','detail',
        'miaosha_start','miaosha_end','is_banner','sort','category_id','unit', 'type','score'
    ];

    protected $casts = [ 'images' => 'array' , 'detail_images' => 'array'];

    protected static function boot()
    {
        parent::boot();
        //登录的如果是商家账号，则只能查询自己商铺的商品
        static::addGlobalScope('store',function (Builder $builder){
            if ($admin = Auth::user()) {//后台登录
                //todo  当前登录用户只要有商铺，就给添加查询作用域
                if ($admin->hasRole('shop')) {
                    $store_id = Store::where('admin_id',Auth::user()->id)->value('id');
                    $builder->where('store_id',$store_id);
                }
            }
        });
    }

    /**
     * 商品的规格型号信息
     * @return HasMany
     */
    function skus(){
        return $this->hasMany('App\Models\ProductSku');
    }

    //商品所属栏目
    function cate() {
        return $this->belongsTo('App\Models\Cate');
    }

    public function category()
    {
        return $this->hasOne(Category::class,"id","category_id");
    }


    /**更新产品的规格型号信息
     * @param array $old_skus 商品原skus信息
     * @param array $request_skus 提交的skus信息
     * @param int   $product_id 商品id
     */
    function update_skus($old_skus,$request_skus,$product_id){
        //提取原规格信息中的id，组成一维索引数组
        $old_sku_ids = array_column($old_skus,'id');
        //提取提交的规格信息中的id，组成一维索引数组
        $request_sku_ids = array_column($request_skus,'id');

        //两个id数组的交集即为需要更新的规格信息
        $update_ids = array_intersect($old_sku_ids,$request_sku_ids);

        //遍历提交的规格，进行更新或者新增处理
        foreach ($request_skus as $request_sku) {
            if (in_array($request_sku['id'],$update_ids)) {//更新
                //组装要更新的规格信息
                $update_data = [
                    'title'         =>  $request_sku['title'],
                    'origin_price'  =>  $request_sku['origin_price'],
                    'sold_price'    =>  $request_sku['sold_price']
                ];
                //判断库存字段是否更新。 todo  修改库存操作独立出来，修改库存时先锁定商品，修改完毕再解锁商品，保证库存的准确。
                //有可能打开编辑页面之后，某规格库存为10。管理员修改商品信息，本意不想修改库存。同时该规格有下单，库存变为了9。
                //然后管理员没有修改库存信息，提交修改，库存又变为了10，导致库存不准。

                //编辑页面的库存和提交的库存不一致时，说明管理员本意是想修改库存的。
                if($request_sku['stock'] != $request_sku['old_stock']) {
                    $update_data['stock'] = $request_sku['stock'];
                }
                ProductSku::where('id',$request_sku['id'])->update($update_data);
            }else {//新增
                //组装要新增的规格信息
                $insert_data = [
                    'title'         =>  $request_sku['title'],
                    'origin_price'  =>  $request_sku['origin_price'],
                    'sold_price'    =>  $request_sku['sold_price'],
                    'stock'         =>  $request_sku['stock'],
                    'product_id'    =>  $product_id
                ];
                ProductSku::create($insert_data);
            }
        }

        //遍历原规格信息，执行下架或者删除处理
        foreach ($old_skus as $old_sku) {
            if (!in_array($old_sku['id'],$request_sku_ids)){
                if (Order::where('product_sku_id',$old_sku['id'])->first()) {
                    //软删除，做下架处理
                    ProductSku::where('id',$old_sku['id'])->delete();
                }else {
                    //删除规格
                    DB::table(self::PRODUCT_SKUS)->where('id',$old_sku['id'])->delete();
                }
            }
        }
    }

    //商品所属商铺
    function store() {
        return $this->belongsTo('App\Models\Store');
    }

    //返回首页banner轮播图商品
    function get_banner() {
        return $this->where('is_banner','>',0)->select('id','cover')->orderBy('is_banner','desc')->get();
    }

    //查询商品列表
    function get_products($where, $category_ids, $offset = 0, $limit = LIMIT) {
        $query = self::query();

        $query->with(['skus'=>function($query){
            $query->where('stock','>',0)
                    ->select('id','product_id','title','sold_price','origin_price','show_sold_num','stock');
        }])->select('id','title','cover','sort','sold_num','description','score');
        if ($where) {
            $query->where($where);
        }
        if ($category_ids) {
            $query->whereIn('category_id', $category_ids);
        }
        $products = $query->orderBy('sort','desc')
                            ->orderBy('id','desc')
                            ->offset($offset)->limit($limit)
                            ->get()->toArray();

        foreach ($products as &$product) {
            $stock = 0;
            $sold_prices = $origin_prices =[];
            foreach ($product['skus'] as $key=>$sku) {
                //计算该产品所有规格型号的累积销量和库存
                // $sold_num += $sku['sold_num'];
                $stock += $sku['stock'];
                //把所有规格型号的售价组成数组
                $sold_prices[$sku['id']] = $sku['sold_price'];
                //把所有规格型号的原价组成数组
                $origin_prices[] = $sku['origin_price'];
            }
            $product['skus_id'] = array_search(min($sold_prices),$sold_prices);
            $product['min_sold_price'] = min($sold_prices);
            $product['min_origin_price'] = min($origin_prices);
            $product['stock'] = $stock;
        }
        return $products;
    }


    /**
     * 查询购物车商品信息
     * @param $cart_ids array   购物车id数组
     * @param $user_id
     * @return \Illuminate\Support\Collection
     */
    public function get_products_by_cart_ids($cart_ids, $user_id) {
        $products =  DB::table('carts')
            ->select('carts.id as cart_id','products.id as product_id','products.title as product_title','products.cover','sku.title AS sku_title','sku.id as sku_id','sku.origin_price','sku.sold_price','sku.stock')
            ->leftJoin('products','products.id','=','carts.product_id')
            ->leftJoin('product_skus as sku','carts.product_sku_id','=','sku.id')
            ->where('user_id', $user_id)
            ->whereIn('carts.id', $cart_ids)->get();

        return $products;
    }

    /**
     * 查询商品的规格型号信息
     * @param $product_id
     * @param $sku_id
     * @return Model|\Illuminate\Database\Query\Builder|object|null
     */
    public function get_product_sku($product_id, $sku_id) {
        $product = DB::table('products')
            ->select('products.id as product_id','products.title as product_title','products.cover','sku.title AS sku_title','sku.id as sku_id','sku.origin_price','sku.sold_price', 'sku.stock')
            ->leftJoin('product_skus as sku','products.id','=','sku.product_id')
            ->where('products.id', $product_id)
            ->where('sku.id', $sku_id)
            ->first();

        return $product;
    }

    /**
     * 根据订单id查询商品信息
     * @param $order_id
     * @return \Illuminate\Support\Collection
     */
    public function get_products_by_order_id($order_id) {
        $products =  DB::table('order_products as op')
            ->select('order_id','op.product_id','products.title as product_title','products.cover','sku.title AS sku_title','op.sku_id','op.origin_price','op.sold_price','op.buynum')
            ->leftJoin('products','products.id','=','op.product_id')
            ->leftJoin('product_skus as sku','op.sku_id','=','sku.id')
            ->where('order_id', $order_id)->get();

        return $products;
    }
}
